﻿using EnvDTE;
using EnvDTE80;
using Microsoft;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Utilities;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Linq;

namespace JoinBoxAlignPlug
{
    [Export(typeof(IWpfTextViewCreationListener))]
    [ContentType("text")]
    [TextViewRole(PredefinedTextViewRoles.Document)]
    internal sealed class EditorViewTextViewCreationListener : IWpfTextViewCreationListener
    {

#pragma warning disable 649, 169
        [Export(typeof(AdornmentLayerDefinition))]
        [Name("EditorView")]
        [Order(After = PredefinedAdornmentLayers.Caret)]
        private AdornmentLayerDefinition editorAdornmentLayer;
#pragma warning restore 649, 169

        #region 添加成员
        [Import]
        internal SVsServiceProvider VsService = null;
        // 事件成员不能移除,否则GC回收
        public static DTE2 VsDTE2 { get; set; }
        Events2 VsEvents2;
        DocumentEvents VsDocumentEvents;
        TextDocumentKeyPressEvents VsTextDocumentKeyPressEvents;

        /// <summary>
        /// 禁用开关
        /// </summary>
        public static bool DisableSave { get; set; } = false;
        #endregion

        /// <summary>
        /// 文件创建之后触发的事件
        /// </summary>
        /// <param name="textView"></param>
        public void TextViewCreated(IWpfTextView textView)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            //获取DTE对象
            VsDTE2 = VsService.GetService(typeof(DTE)) as DTE2;
            Assumes.Present(VsDTE2);

            //文档保存的事件
            VsEvents2 = (Events2)VsDTE2.Events;
            VsDocumentEvents = VsEvents2.DocumentEvents;
            VsDocumentEvents.DocumentSaved += DocumentEvents_DocumentSaved;

            //拦截键盘
            VsTextDocumentKeyPressEvents = VsEvents2.TextDocumentKeyPressEvents;
            VsTextDocumentKeyPressEvents.BeforeKeyPress += VsTextDocumentKeyPressEvents_BeforeKeyPress;
            VsTextDocumentKeyPressEvents.AfterKeyPress += VsTextDocumentKeyPressEvents_AfterKeyPress;
        }



        /// <summary>
        /// 按键之前
        /// </summary>
        private void VsTextDocumentKeyPressEvents_BeforeKeyPress(string Keypress, TextSelection Selection, bool InStatementCompletion, ref bool CancelKeypress)
        {

        }

        const string _triggerKey = "`";//因为Tab键"\t" 会触发基础提示,不好,换另一个
        static bool _FlagLineContainUpDot = false;
        static CodeLineSuffixRepair _ts = null;
        static string[] _keysJump = new string[] { "\b" };                  //跳过字符 删除键跳过
        static string[] _keysBreak = new string[] { " ", "\t", "\n", "\r" };//中断字符
        static Dictionary<string, FileInfo> dictionary = null;

        /// <summary>
        /// 按键之后
        /// </summary>
        private void VsTextDocumentKeyPressEvents_AfterKeyPress(string Keypress, TextSelection Selection, bool InStatementCompletion)
        {
#pragma warning disable VSTHRD010
            if (Keypress == _triggerKey)//第1次:触发了`
            {
                if (dictionary == null)
                    dictionary = SnippetHelper.GetCsSnippet(VsDTE2);

                _FlagLineContainUpDot = true;
                _ts?.Dispose();
                _ts = new CodeLineSuffixRepair(VsDTE2, _triggerKey, dictionary);
                _ts.GetDocEnvironment();
            }
            else if (_FlagLineContainUpDot && !_keysJump.Contains(Keypress))//第2次:轮询
            {
                //遇到这些东西就放弃
                if (_keysBreak.Contains(Keypress))
                {
                    _FlagLineContainUpDot = false;
                    return;
                }
                //`号之后,轮询`后面的字符,字符串为c#保留词就修改内容
                bool changOk = _ts.ChangDocText(out bool upDotIsNull);

                //`号之后,删除了`就会一直轮询,因此需要立马结束掉
                if (upDotIsNull)
                {
                    _FlagLineContainUpDot = false;
                    return;
                }
                if (changOk)
                    _FlagLineContainUpDot = false;//修改成功就还原
            }
#pragma warning restore VSTHRD010
        }


        /// <summary>
        /// 保存事件
        /// </summary>
        private void DocumentEvents_DocumentSaved(Document Document)
        {
            //禁用 或者 防止重复触发保存事件
            if (DisableSave)
                return;

            ThreadHelper.ThrowIfNotOnUIThread();
            JoinBoxCommand.Execute(VsDTE2, Document);
            if (!Document.Saved)
            {
                DisableSave = true;
                Document.Save();
                DisableSave = false;
            }
        }


    }
}


